use actix::{Actor, ActorContext, Addr, AsyncContext, Recipient, SpawnHandle, StreamHandler};
use actix_web_actors::ws;

use super::{
    handle::{SessionMessage, WebrtcConnection, WebrtcDisConnection, WebrtcMessage},
    webrtc::WebrtcServer,
};

pub struct WebrtcSession {
    pub id: usize,
    pub addr: Addr<WebrtcServer>,
}

impl Actor for WebrtcSession {
    type Context = ws::WebsocketContext<Self>;

    fn started(&mut self, ctx: &mut Self::Context) {
        let addr = ctx.address();
        let reci: Recipient<SessionMessage> = addr.recipient();
        self.addr.do_send(WebrtcConnection { id: self.id, reci });
    }

    fn stopped(&mut self, ctx: &mut Self::Context) {
        self.addr.do_send(WebrtcDisConnection { id: self.id });
    }
}

impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for WebrtcSession {
    fn handle(&mut self, item: Result<ws::Message, ws::ProtocolError>, ctx: &mut Self::Context) {
        let msg = match item {
            Err(_) => {
                ctx.stop();
                return;
            }
            Ok(msg) => msg,
        };

        match msg {
            ws::Message::Ping(msg) => {
                ctx.pong(&msg);
            }
            ws::Message::Pong(_) => {}
            ws::Message::Close(msg) => {
                ctx.close(msg);
                ctx.stop();
            }
            ws::Message::Continuation(_) => {
                ctx.stop();
            }
            ws::Message::Nop => (),
            ws::Message::Binary(_) => {
                println!("Message::Binary");
            }
            ws::Message::Text(msg) => self.addr.do_send(WebrtcMessage { id: self.id, msg }),
        }
    }
}
